package com.heima.admin.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.heima.admin.entity.AdChannel;
import com.heima.admin.service.IAdChannelService;
import com.heima.admin.service.IAdSensitiveService;
import com.heima.admin.service.WemediaNewsAutoService;
import com.heima.article.client.ArticleFeign;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.dtos.PageResult;
import com.heima.common.dtos.ResponseResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.util.JsonUtils;
import com.heima.common.util.SensitiveWordUtil;
import com.heima.model.admin.dtos.NewsAuthDto;
import com.heima.model.media.dtos.WmNewsDto;
import com.heima.model.media.dtos.WmNewsResultDTO;
import com.heima.wemedia.client.WemediaFeign;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

import static com.heima.common.constants.message.Article2EsConstants.ARTICLE_2_ES_TOPIC;

@Slf4j
@Service
public class WemediaNewsAutoServiceImpl implements WemediaNewsAutoService {

    @Autowired
    private WemediaFeign wemediaFeign;

    @Autowired
    private IAdSensitiveService sensitiveService;

    @Autowired
    private GreenTextScan textScan;

    @Autowired
    private GreenImageScan imageScan;

    @Autowired
    private ArticleFeign articleFeign;

    @Autowired
    private IAdChannelService channelService;

    @Autowired
    private KafkaTemplate kafkaTemplate;


    @Override
    @GlobalTransactional
    public void auditWemediaNews(Integer wmNewsId) {
        //1、根据自媒文章id查询自媒体文章
        ResponseResult<WmNewsResultDTO> responseResult = wemediaFeign.findById(wmNewsId);
        WmNewsResultDTO wmNewDto = responseResult.getData();
        //2、校验查询结果，有数据再进一步获取自媒体文章状态
        if(responseResult==null || wmNewDto ==null || responseResult.getCode()!=0){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"自媒体文章数据不存在");
        }
        //3、获取自媒体文章状态
        Integer status = wmNewDto.getStatus();
        //3.1 如果自媒体文章是待审核状态 1
        if(status==1){
            //获取文章的内容（包含标题、文本内容）和文章图片（包含文章内容中图片和封面图片）  Map<String,Object>
           Map<String,Object> contentMap = getTextAndImage(wmNewDto.getTitle(),wmNewDto.getContent(),wmNewDto.getImages());
            String text = String.valueOf(contentMap.get("text"));
            //获取图片列表
            List<String> imageList = (List<String>) contentMap.get("image");
            //               检查自定义敏感词
            //查询数据库中自定义的所有敏感词
            List<String> sensitiveList = sensitiveService.findAllSensitive();
            Boolean b = handleSensitive(sensitiveList,text,wmNewsId);
            if(!b){
                return;
            }
//               调用阿里云的接口审核文字
            Boolean b1 = handleTextByAliyun(text,wmNewsId);
            if(!b1){
                return;
            }
//               调用阿里云的接口审核图片
            Boolean b2 = handleImageByAliyun(imageList,wmNewsId);
            if(!b2){
                return;
            }
//               如果上面的检查都通过,远程调用-修改自媒体文章状态为8-审核通过
            updateWmNews(wmNewsId,"审核通过",WmNewsDto.Status.SUCCESS.getCode());
            //判断发布时间是否大于当前时间，直接返回即可，等待到达发布时候后，发布即可
            if(wmNewDto.getPublishTime()!=null && wmNewDto.getPublishTime().getTime()>System.currentTimeMillis()){
                return;
            }
        }
//           如果是 4 -人工审核通过，或者审核通过待发布 8
//           远程调用自媒体微服务更正状态为已发布 9
        updateWmNews(wmNewsId,"审核通过，已发布",WmNewsDto.Status.PUBLISHED.getCode());
        //远程调用 -保存自媒体文章信息到文章库
        //封装频道名称
        AdChannel channel = channelService.getById(wmNewDto.getChannelId());
        wmNewDto.setChannelName(channel.getName());
        Long articleId = articleFeign.saveArticle(wmNewDto);
        //将审核通过，且已发布的文章同步到索引库
        kafkaTemplate.send(ARTICLE_2_ES_TOPIC,articleId);
    }

    @Override
    public void wemediaAutoAudit() {
        //通过feign远程调用自媒体微服务，查询审核通过待发布文章id列表
        List<Integer> wmNewsIds = wemediaFeign.findWmNewsIds();
        for (Integer wmNewsId : wmNewsIds) {
            //自动审核即可
            auditWemediaNews(wmNewsId);
        }
    }

    @Override
    public PageResult<WmNewsResultDTO> findWmNewsList(NewsAuthDto dto) {
        return wemediaFeign.findList(dto);
    }

    @Override
    public ResponseResult<WmNewsResultDTO> findOneWmNews(Integer id) {
        return wemediaFeign.findById(id);
    }

    /**
     * 调用阿里云的接口审核图片
     * @param imageList
     * @param wmNewsId
     * @return
     */
    private Boolean handleImageByAliyun(List<String> imageList, Integer wmNewsId) {
        try {
            Map<String, String> map = imageScan.imageScan(imageList);
            String suggestion = map.get("suggestion");
            if("pass".equals(suggestion)){
                return true;
            }
            Integer status= "review".equals(suggestion)?WmNewsDto.Status.ADMIN_AUTH.getCode():WmNewsDto.Status.FAIL.getCode();
            //更正自媒体文章状态
            updateWmNews(wmNewsId,map.get("label"),status);
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"调用阿里云图片审核失败");
        }
    }

    /**
     * 调用阿里云的接口审核文字
     * @param text
     * @param wmNewsId
     * @return
     */
    private Boolean handleTextByAliyun(String text, Integer wmNewsId) {
        //调用阿里云文本审核
        try {
            Map<String, String> map = textScan.greenTextScan(text);
            String suggestion = map.get("suggestion");
            if("pass".equals(suggestion)){
                return true;
            }
            Integer status= "review".equals(suggestion)?WmNewsDto.Status.ADMIN_AUTH.getCode():WmNewsDto.Status.FAIL.getCode();
            //更正自媒体文章状态
           updateWmNews(wmNewsId,map.get("reson"),status);
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"调用阿里云文本审核失败");
        }
    }

    /**
     * 检查自定义敏感词
     * @param sensitiveList
     * @param text
     * @param wmNewsId
     * @return
     */
    private Boolean handleSensitive(List<String> sensitiveList, String text, Integer wmNewsId) {
        Map<String, Integer> map = SensitiveWordUtil.matchWords(sensitiveList, text);
        if(!CollectionUtils.isEmpty(map)){
            //文本内容存在敏感词，审核失败，更新自媒体文章状态
            updateWmNews(wmNewsId,"存在自定义敏感词",WmNewsDto.Status.FAIL.getCode());
            return false;
        }
        return true;
    }

    /**
     * 抽取更正自媒体文章状态方法
     */
    @Override
    public void updateWmNews(Integer wmNewsId,String reason,Integer status){
        WmNewsDto wmNewsDto = new WmNewsDto();
        wmNewsDto.setId(wmNewsId);
        wmNewsDto.setReason(reason);
        wmNewsDto.setStatus(status);
        wemediaFeign.updateWmNews(wmNewsDto);
    }

    /**
     * 解析文章内容和图片
     * @param title
     * @param content
     * @param images
     * @return
     */
    private Map<String, Object> getTextAndImage(String title, String content, String images) {
        if(StringUtils.isBlank(title) || StringUtils.isBlank(content)){
            throw new LeadException(AppHttpCodeEnum.PARAM_INVALID);
        }
        //[{"type":"text","value":"Redis 数据类型 Redis支持五种数据类型：string（字符串），hash（哈希），list（列表），set（集合）及zset(sorted set：有序集合)"},{"type":"image","value":"https://heima-leadnews.oss-cn-beijing.aliyuncs.com/f70eac9b-7bf5-444a-9471-b3a4a4ccbe38.png"}]
        List<Map<String, String>> contentList = JsonUtils.nativeRead(content, new TypeReference<List<Map<String, String>>>() {});
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(title);
        //封装图片地址的集合
        List<String> imageList = new ArrayList<>();
        for (Map<String, String> map : contentList) {
            //处理文章内容中的文本
            if("text".equals(map.get("type"))){
                stringBuilder.append(map.get("value"));
            }
            //处理文章内容中的图片
            if("image".equals(map.get("type"))){
                String imageUrl = map.get("value");
                imageList.add(imageUrl);
            }
        }

        //处理文章的封面图片
        if(StringUtils.isNotBlank(images)){
            List<String> imageUrlList = Arrays.asList(images.split(","));
            imageList.addAll(imageUrlList);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("text",stringBuilder);
        map.put("image",imageList);
        return map;

    }
}
